iT邦幫忙

2024 iThome 鐵人賽

DAY 21
0
Modern Web

現在就學React.js 系列 第 21

告別不必要的渲染:理解 React useRef -Day21

  • 分享至 

  • xImage
  •  

在 React 中,我們經常使用 useState 來管理組件的狀態,並讓組件隨著狀態的變化重新渲染。不過在某些情況,不希望狀態變更時觸發重新渲染,這時就可以使用 useRef 來保存狀態,或是引用 DOM 元素來操作。

useRef 基本語法

當你呼叫 useRef 時,它會回傳一個包含 current 屬性的物件。這個 current 可以用來保存我們想要記住的值,且不會隨著重新渲染而丟失。

const ref = useRef(initialValue);
  • initialValue 是用來設定 current 的初始值。
  • useRef 返回的物件(ref)中的 current 屬性會保存這個值。

useRef 的使用時機

1. 保存狀態但不觸發重新渲染

當我們需要在 React 中保存某些資料,但不希望資料變更時觸發組件的重新渲染,可以使用 useRef。一個常見的例子是儲存表單中的輸入值,或是在某個事件觸發時保存資料,這些資料不會影響畫面的顯示。

2. 存取 DOM 元素

useRef 也可以用來存取 DOM 元素的引用。在 React 中,很少直接操作 DOM 元素,例如用document.querySelector的方式取得DOM,但在某些情況下,操作 DOM 是會需要用到的。例如,當需要聚焦到某個表單輸入欄位,或滾動到特定位置時,可以使用 useRef 來存取該元素的 DOM 引用。

useRef 保存狀態

useState 每次變更狀態時,會觸發重新渲染組件,但有些狀態我們並不想讓它引發重新渲染。使用 useRef 可以避免這個問題。

範例:用 useRef 來實作一個不會觸發重新渲染的計數器:

import React, { useRef, useState } from 'react';

function Counter() {
  const countRef = useRef(0);  // 使用 useRef 保存計數器值
  const [renderCount, setRenderCount] = useState(0);  // 控制組件重新渲染的狀態

  const incrementCount = () => {
    countRef.current += 1;  // 使用 useRef 的 current 更新計數器值
    console.log("計數器值:", countRef.current);
  };

  return (
    <div>
      <p>計數器值不會觸發重新渲染: {countRef.current}</p>
      <p>畫面重新渲染次數: {renderCount}</p>
      <button onClick={incrementCount}>增加計數器值</button>
      <button onClick={() => setRenderCount(renderCount + 1)}>強制重新渲染</button>
    </div>
  );
}

export default Counter;

在這個範例中,countRef 儲存了計數器的值,但它並不會觸發重新渲染。即便點擊「增加計數器值」按鈕,畫面顯示的數值也不會變動;要強制重新渲染,則可以點擊「強制重新渲染」按鈕。這顯示了 useRef 不會觸發重新渲染的特性。

當按下七次計數器之後,只有在 console.log 上顯示,畫面卻沒有更新。

https://ithelp.ithome.com.tw/upload/images/20241005/20159895BBYX1nYrHQ.png

但用 useState 的值更新後,countRef 的值就會被更新到畫面上。

https://ithelp.ithome.com.tw/upload/images/20241005/20159895FW4kZ6pJAz.png

useRef 存取 DOM 元素

useRef 的另一個常見用途是直接存取 DOM 元素。我們可以用 useRef 來引用 HTML 元素,並進行聚焦、滾動等 DOM 操作。

範例:自動聚焦到輸入框

當組件渲染後,我們可以使用 useRef 來讓一個輸入框自動獲得焦點。


import React, { useRef, useEffect } from 'react';

function AutoFocusInput() {
  const inputRef = useRef(null);  // 使用 useRef 來引用 DOM 元素

  useEffect(() => {
    inputRef.current.focus();  // 當組件渲染後,讓輸入框自動獲得焦點
  }, []);

  return (
    <div>
      <input ref={inputRef} placeholder="自動聚焦的輸入框" />
    </div>
  );
}

export default AutoFocusInput;

在這個範例中,我們使用了 inputRef 來引用輸入框,並在 useEffect 中讓這個輸入框在組件渲染後自動獲得焦點。這就是操作 DOM 元素的典型用法。

結論:

useRef 能夠幫助我們:

  1. 保存狀態:避免狀態變更引發不必要的重新渲染。
  2. 存取 DOM 元素:在需要操作 DOM 元素時,使用 useRef 提供了方便的引用方式。

useState 不同,useRef 不會觸發組件的重新渲染。當我們需要記住一些資料而不影響 UI 的時,useRef 是一個理想的選擇。另外再需要操作 DOM 元素時也能應用到。

參考資料:

使用 ref 引用值 – React 中文文档

Day 08 - 掌握 React 中的 Ref:useRef、Callback Ref 與 React 19 新特性介紹 - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天 (ithome.com.tw)

後記

本文將會同步更新到我的部落格

黃禎平 – Medium


上一篇
在 React 中使用 Axios 進行非同步請求 - Day20
下一篇
useContext 輕鬆共享資料之props drilling的解方 - Day22
系列文
現在就學React.js 31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言